﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Contract;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace ConsoleApplication1
{
    class Program  
    {
        private static List<IPAddress> agentsIP = new List<IPAddress>();
        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(Service_Allocation));

            NetTcpBinding binding = new NetTcpBinding();
            binding.TransferMode = TransferMode.Streamed;
            binding.ReceiveTimeout = TimeSpan.MaxValue;
            binding.MaxReceivedMessageSize = long.MaxValue;

            host.AddServiceEndpoint(typeof(IService_Allocation), binding,
            new Uri("net.tcp://localhost:8888/Service_Allocation"));

            host.Open();
            Timer t = new Timer(Service_Allocation.ComputeBoundOp, null,0,10000);
            

        }


        public class Service_Allocation : IService_Allocation
        {
            //sort the list of ip
            public static void ComputeBoundOp(Object state)
            {
                NetTcpBinding binding = new NetTcpBinding();
                binding.TransferMode = TransferMode.Streamed;
                binding.MaxReceivedMessageSize = 200000000000000;
                binding.SendTimeout = TimeSpan.MaxValue;
                EndpointAddress address = new EndpointAddress("net.tcp://" + agentsIP[0].ToString() + ":8000/DataUploader");
                ChannelFactory<IDataUploader> channel =
                new ChannelFactory<IDataUploader>(binding, address);
                IDataUploader Proxy = channel.CreateChannel();
                IPAddress targetAgent = agentsIP[0];
                int con = Proxy.returnNumOfConnections();
                foreach (IPAddress ip in agentsIP)
                {
                    address = new EndpointAddress("net.tcp://" + ip.ToString() + ":8000/DataUploader");
                    channel = new ChannelFactory<IDataUploader>(binding, address);
                    Proxy = channel.CreateChannel();
                    if (con >= Proxy.returnNumOfConnections())
                    {
                        targetAgent = ip;
                    }
                    con = Proxy.returnNumOfConnections();
                }
             //   return targetAgent;
            }

            // calculate the agent with least ip addres
            public IPAddress agentAllocation()
            {
                NetTcpBinding binding = new NetTcpBinding();
                binding.TransferMode = TransferMode.Streamed;
                binding.MaxReceivedMessageSize = 200000000000000;
                binding.SendTimeout = TimeSpan.MaxValue;
                EndpointAddress address = new EndpointAddress("net.tcp://" + agentsIP[0].ToString() + ":8000/DataUploader");
                ChannelFactory<IDataUploader> channel = new ChannelFactory<IDataUploader>(binding, address);
                IDataUploader Proxy = channel.CreateChannel();
                IPAddress targetAgent = agentsIP[0];
                int con = Proxy.returnNumOfConnections();

                foreach (IPAddress ip in agentsIP)
                {
                    address = new EndpointAddress("net.tcp://" + ip.ToString() + ":8000/DataUploader");
                    channel = new ChannelFactory<IDataUploader>(binding, address);
                    Proxy = channel.CreateChannel();

                    if (con >= Proxy.returnNumOfConnections())
                    {
                        targetAgent = ip;
                    }
                    con = Proxy.returnNumOfConnections();

                }
                return targetAgent;
            }

            //agents add their ip to this project
            public void registerAgent(IPAddress ip)
            {
                agentsIP.Add(ip);
            }

            public List<IPAddress> AllAgents()
            {
                return agentsIP;
            }

        }
    }
}
